package cn.tedu.product.service;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.tedu.common.pojo.EasyUIResult;
import cn.tedu.common.pojo.Product;
import cn.tedu.common.utils.MapperUtil;
import cn.tedu.product.mapper.ProductMapper;
import redis.clients.jedis.JedisCluster;

@Service
public class ProductService {
	/*
	 * 根据控制层参数,到持久层获取分页查询的数据
	 */
	@Autowired
	private ProductMapper productMapper;
	public EasyUIResult pageQuery(Integer page, Integer rows) {
		//sql语句:select * from table limit #{start},#{rows}
		int start=(page-1)*rows;
		//封装EasyUIResult total select count(*)
		//List<Product>
		EasyUIResult result=new EasyUIResult();
		List<Product> pList=productMapper.pageQuery(start,rows);
		Integer total=productMapper.queryCount();
		//封装数据
		result.setRows(pList);
		result.setTotal(total);
		return result;
	}
	@Autowired
	private JedisCluster jedis;
	public Product queryById(String productId) {
		//select * from t_product where product_id=#{}
		//根据id生成一个key
		String key="product_query_id_"+productId;
		//实现缓存逻辑
		//5分钟之内发送最多3条验证码--思考题
		String lock="update_"+productId+".lock";
		if(jedis.exists(lock)){//直接获取数据库数据返回
			return productMapper.queryById(productId);
		}
		try{
			if(jedis.exists(key)){//redis存在数据
				//将缓存数据获取
				String data=jedis.get(key);
				//TODO 解析成product对象返回 data是json
				Product product=MapperUtil.MP.readValue(data, Product.class);
				return product;
			}else{//缓存没有数据,从数据库获取
				Product product=productMapper.queryById(productId);
				//将数据存储在缓存一份,供后续使用
				//转化成json字符串
				String jsonData=MapperUtil.MP.writeValueAsString(product);
				jedis.setex(key, 60*60*24*2,jsonData);
				return product;
			}
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	public void saveProduct(Product product) {
		//TODO redis缓存存储数据
		//TODO 补充完成product的数据
		String productId=UUID.randomUUID().toString();
		product.setProductId(productId);
		productMapper.saveProduct(product);
	}
	public void updateProduct(Product product) {
		//生成锁的key
		String lock="udpate_"+product.getProductId()+".lock";
		jedis.setex(lock,60*60*24*2,"");
		//删除缓存
		String key="product_query_id_"+product.getProductId();
		jedis.del(key);
		productMapper.updateProduct(product);
		jedis.del(lock);
	}
	public void createIndex(String indexName) throws Exception {
		//读取数据源,select * from t_product limit #{start},#{rows}
		List<Product> pList=productMapper.pageQuery(0, 800);
		//lucene创建索引代码
		Path path = Paths.get("d://"+indexName);
		FSDirectory dir = FSDirectory.open(path);
		IndexWriterConfig config=
				new IndexWriterConfig(new SmartChineseAnalyzer());
		config.setOpenMode(OpenMode.CREATE);
		IndexWriter writer=new IndexWriter(dir,config);
		for (Product p : pList) {
			//循环一次,封装一个document数据
			Document doc=new Document();
			//productName ,productPrice,productImage,productDesc
			//productNum
			doc.add(new TextField("productName",p.getProductName(),Store.YES));
			doc.add(new TextField("productDescription",p.getProductDescription(),Store.NO));
			doc.add(new StringField("productImgurl",p.getProductImgurl(),Store.YES));
			doc.add(new StringField("productNum",p.getProductNum()+"",Store.YES));
			doc.add(new DoublePoint("productPrice",p.getProductPrice()));
			doc.add(new StringField("productPrice",p.getProductPrice()+"",Store.YES));
			writer.addDocument(doc);
		}
		writer.commit();
	}
	public List<Product> search(String indexName, String value) throws Exception {
		//指定文件夹
		Path path = Paths.get("d://"+indexName);
		FSDirectory dir = FSDirectory.open(path);
		//先获取reader
		IndexReader reader=DirectoryReader.open(dir);
		//封装搜索对象
		IndexSearcher search=new IndexSearcher(reader);
		
		//封装不同功能的查询条件query
		Analyzer analyzer=new SmartChineseAnalyzer();
		//准备多个域
		String[] fields={"productName","productDescription"};
		//包装了分词器的条件关键字字符串解析器parser
		MultiFieldQueryParser parser=
				new MultiFieldQueryParser(fields, 
						analyzer);
		//生成查询条件query
		Query query=parser.parse(value);

		//获取结果集遍历打印数据
		//获取top10前10条数据
		TopDocs topDoc = search.search(query, 10);
		System.out.println("总共搜索到"+topDoc.totalHits+"条");
		//topDoc当中封装了带有评分的结果信息,带有docid信息的数据返回
		ScoreDoc[] scoreDoc=topDoc.scoreDocs;
		//准备一个返回结果
		List<Product> pList=new ArrayList<Product>();
		//scoreDoc除了保存了每个查询结果document的id还有评分
		for (ScoreDoc score: scoreDoc) {
			int docid=score.doc;
			Document doc = search.doc(docid);
			Product p=new Product();
			p.setProductName(doc.get("productName"));
			p.setProductPrice(Double.parseDouble(doc.get("productPrice")));
			p.setProductNum(Integer.parseInt(doc.get("productNum")));
			p.setProductImgurl(doc.get("productImgurl"));
			pList.add(p);
		}
		return pList;
	}
}


















